package cc.rengu.igas.bsps.core.service.trans;

import cc.rengu.igas.bsps.common.constant.BspsAppParamConstant;
import cc.rengu.igas.bsps.common.constant.DubboMethodConstant;
import cc.rengu.igas.bsps.common.dao.BspsMchntSignInfoMapper;
import cc.rengu.igas.bsps.common.dao.BspsUserInfoMapper;
import cc.rengu.igas.bsps.common.dao.impl.BspsMchntSignInfoMapperImpl;
import cc.rengu.igas.bsps.common.dao.impl.BspsUserInfoMapperImpl;
import cc.rengu.igas.bsps.common.entity.MchntSignInfo;
import cc.rengu.igas.bsps.common.entity.UserInfo;
import cc.rengu.igas.bsps.common.enums.BspsMchntTypeEnum;
import cc.rengu.igas.bsps.common.enums.RespCodeEnum;
import cc.rengu.igas.bsps.core.model.UserSessionInfo;
import cc.rengu.igas.bsps.core.service.base.ManageService;
import cc.rengu.igas.bsps.facade.request.ApplySmsCodeRequest;
import cc.rengu.igas.bsps.facade.response.ApplySmsCodeResponse;
import cc.rengu.igas.share.common.util.GlobalEsbUtil;
import cc.rengu.igas.share.common.util.SensitiveDataUtil;
import cc.rengu.igas.share.core.model.AgentMchntInfo;
import cc.rengu.igas.share.core.model.GroupMchntInfo;
import cc.rengu.igas.share.core.model.MchntInfo;
import cc.rengu.igas.share.core.model.PlatMchntInfo;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.igas.smps.facade.base.Header;
import cc.rengu.igas.smps.facade.request.GeneralSmsNoticeRequest;
import cc.rengu.igas.smps.facade.response.GeneralSmsNoticeResponse;
import cc.rengu.igas.smps.facade.result.Result;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.dao.MsgTemplateCfgMapper;
import cc.rengu.oltp.service.common.dao.impl.MsgTemplateCfgMapperImpl;
import cc.rengu.oltp.service.common.entity.ChannelCallCfg;
import cc.rengu.oltp.service.common.entity.MsgTemplateCfg;
import cc.rengu.oltp.service.common.entity.SmsInfo;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.common.enums.SmsTypeEnum;
import cc.rengu.oltp.service.common.enums.TemplateTypeEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.realize.DubboService;
import cc.rengu.oltp.service.realize.SmsService;
import cc.rengu.oltp.service.realize.impl.DubboServiceImpl;
import cc.rengu.oltp.service.realize.impl.SmsServiceImpl;
import cc.rengu.oltp.utility.util.ConvertUtil;
import cc.rengu.oltp.utility.util.RedisUtil;
import cc.rengu.oltp.utility.util.StringUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * 申请短信验证码服务
 * Created by 王成 on 2018/6/14.
 *
 * @author zhangxuran (联调修改)
 * @version 1.0
 * @date 2020.04.08
 */
public class ApplySmsCodeService extends ManageService {
    @Override
    protected Object bizBeforeCust() throws Exception {
        ApplySmsCodeRequest applySmsCodeRequest = new ApplySmsCodeRequest();
        ConvertUtil.convertOutput(applySmsCodeRequest);
        return applySmsCodeRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        ApplySmsCodeRequest applySmsCodeRequest = (ApplySmsCodeRequest) request;
        ApplySmsCodeResponse applySmsCodeResponse = new ApplySmsCodeResponse();
        String instId = applySmsCodeRequest.getHeader().getInstId();
        String userId = applySmsCodeRequest.getUserId();
        String imageAuthCode = applySmsCodeRequest.getImageAuthCode();
        String mchntNo = applySmsCodeRequest.getMchntNo();
        String phoneNo = applySmsCodeRequest.getPhoneNo();
        String smsType = applySmsCodeRequest.getSmsType();
        String sessionId = applySmsCodeRequest.getHeader().getSession();

        if (StringUtil.isEmptyOrNull(instId) || (StringUtil.isEmptyOrNull(mchntNo) && StringUtil.isEmptyOrNull(phoneNo)) || StringUtil.isEmptyOrNull(imageAuthCode)
                || StringUtil.isEmptyOrNull(smsType)) {
            rglog.error("必填性校验失败！");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        /* 获取短信模板枚举类型 */
        TemplateTypeEnum templateTypeEnum = SmsTypeEnum.getTemplateTypeEnum(smsType);
        if (null == templateTypeEnum) {
            rglog.error("不支持的验证码类型!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }
        /* 获取通道交易码 */
        Optional<ChannelCallCfg> channelCallCfgOpt = txnInfo.getChannelCallCfgList().stream().filter(item -> item.getCallChannelId().equals(ChannelEnum.ESB.getChannelType())).findFirst();
        if (!channelCallCfgOpt.isPresent()) {
            rglog.error("未配置通道的通道服务调用配置,txnKey:<{}>,msgDstId:<{}>", txnInfo.getTxnKey(), ChannelEnum.ESB.getChannelType());
            throw new BizException(RespCodeEnum.NOT_CONF_CHANNEL_TXN_MAP.getRespCode(), RespCodeEnum.NOT_CONF_CHANNEL_TXN_MAP.getRespDesc());
        }
        /* 校验图片验证码 */
        String userSessionString = RedisUtil.onceGet(sessionId);
        if (StringUtil.isEmptyOrNull(sessionId) || StringUtil.isEmptyOrNull(userSessionString)) {
            rglog.error("用户未登录或者Session已过期!");
            throw new BizException(RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespCode(), RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespDesc());
        }
        UserSessionInfo userSessionInfo = JSON.parseObject(userSessionString, UserSessionInfo.class);

        /* 根据商户号获取商户法人手机号 */
        String mobileNo = applySmsCodeRequest.getPhoneNo();
        if (!StringUtil.isEmptyOrNull(applySmsCodeRequest.getMchntNo())) {
            String mchntType = xmlTreeUtil.getXmlTreeStringValue("mchntType");
            /*没有传商户类型*/
            if (StringUtil.isEmptyOrNull(mchntType)) {
                //普通商户
                MchntService mchntService = new MchntServiceImpl();
                MchntInfo mchntInfo = mchntService.getMchntInfo(instId, mchntNo);
                if (mchntInfo != null) {
                    BspsMchntSignInfoMapper bspsMchntSignInfoMapper = new BspsMchntSignInfoMapperImpl();
                    MchntSignInfo mchntSignInfo = bspsMchntSignInfoMapper.selectBspsMchntSignInfoByPrimaryKey(instId, mchntNo);
                    if (null == mchntSignInfo) {
                        rglog.error("查询商户签约信息失败,instId:<{}>,mchntNo:<{}>", applySmsCodeRequest.getHeader().getInstId(), applySmsCodeRequest.getMchntNo());
                        throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
                    }
                    mobileNo = mchntSignInfo.getArtifMobile();
                } else {
                    //平台商户
                    PlatMchntInfo platMchntInfo = mchntService.getPlatMchntInfo(instId, mchntNo);
                    if (platMchntInfo != null) {
                        mobileNo = platMchntInfo.getContactPhone();
                    } else {
                        //代理商商户
                        AgentMchntInfo agentMchntInfo = mchntService.getAgentMchntInfo(instId, mchntNo);
                        if (agentMchntInfo != null) {
                            mobileNo = agentMchntInfo.getContactPhone();
                        } else {
                            //集团商户
                            GroupMchntInfo groupMchntInfo = mchntService.getGroupMchntInfo(instId, mchntNo);
                            if (groupMchntInfo != null) {
                                mobileNo = groupMchntInfo.getContactPhone();
                            } else {
                                throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
                            }
                        }
                    }
                }

            } else {
                if (BspsMchntTypeEnum.PLAT_MCHNT.getMchntType().equals(mchntType) || BspsMchntTypeEnum.GROUP_MCHNT.getMchntType().equals(mchntType) || BspsMchntTypeEnum.AGENT_MCHNT.getMchntType().equals(mchntType)) {
                    mobileNo = xmlTreeUtil.getXmlTreeStringValue("mchntPhone");
                } else {
                    BspsMchntSignInfoMapper bspsMchntSignInfoMapper = new BspsMchntSignInfoMapperImpl();
                    MchntSignInfo mchntSignInfo = bspsMchntSignInfoMapper.selectBspsMchntSignInfoByPrimaryKey(instId, mchntNo);
                    if (null == mchntSignInfo) {
                        rglog.error("查询商户签约信息失败,instId:<{}>,mchntNo:<{}>", applySmsCodeRequest.getHeader().getInstId(), applySmsCodeRequest.getMchntNo());
                        throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
                    }
                    mobileNo = mchntSignInfo.getArtifMobile();
                }
            }

        }

        /* 04-重置密码交易，单独获取手机号 */
        if ("04".equals(smsType)) {
            if (StringUtil.isEmptyOrNull(userId)) {
                rglog.error("必填性校验失败！");
                throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
            } else {
                /* 根据用户登录ID获取手机号 */
                UserInfo userInfo;
                BspsUserInfoMapper bspsUserInfoMapper = new BspsUserInfoMapperImpl();
                userInfo = bspsUserInfoMapper.selectBspsUserInfoByUserLoginId(instId, userId);
                if (null != userInfo && !StringUtil.isEmptyOrNull(userInfo.getMobileNo())) {
                    mobileNo = userInfo.getMobileNo();
                }
            }
        }

        /* 生成短信验证码 */
        rglog.info("mobileNo:" + mobileNo);
        SmsService smsService = new SmsServiceImpl();
        SmsInfo smsInfo = smsService.generateSmsCode(applySmsCodeRequest.getHeader().getInstId(), mobileNo, applySmsCodeRequest.getSmsType());
        if (null == smsInfo) {
            rglog.error("生成短信验证码失败!");
            throw new BizException(RespCodeEnum.GEN_SMS_CODE_ERROR.getRespCode(), RespCodeEnum.GEN_SMS_CODE_ERROR.getRespDesc());
        } else {
            applySmsCodeResponse.setVerifySeqNum(smsInfo.getVerifySeqNum());
        }
        /* 获取短信模板 */
        MsgTemplateCfgMapper msgTemplateCfgMapper = new MsgTemplateCfgMapperImpl();
        MsgTemplateCfg msgTemplateCfg = msgTemplateCfgMapper.selectMsgTemplateCfgByTemplateType(applySmsCodeRequest.getHeader().getInstId(), templateTypeEnum.getTemplateType());
        if (null == msgTemplateCfg) {
            msgTemplateCfg = msgTemplateCfgMapper.selectMsgTemplateCfgByTemplateType(AppParamConstant.DEFAULT_INSTID, templateTypeEnum.getTemplateType());
            if (null == msgTemplateCfg) {
                rglog.error("未配置短信发送模板!");
                throw new BizException(RespCodeEnum.NOT_CONF_MSG_TEMPLATE.getRespCode(), RespCodeEnum.NOT_CONF_MSG_TEMPLATE.getRespDesc());
            }
        }
        rglog.debug("短信模板代码:<{}>,短信模板内容:<{}>", msgTemplateCfg.getTemplateCode(), msgTemplateCfg.getTemplateDesc());
        String smsContent = parseSmsTemplateInfo(msgTemplateCfg.getTemplateDesc(), smsInfo.getSmsCode());
        /* 调用支付通道发送短信 */
        DubboService dubboService = new DubboServiceImpl();
        Header header = new Header();
        header.setVersion(applySmsCodeRequest.getHeader().getVersion());
        header.setTransDate(applySmsCodeRequest.getHeader().getTransDate());
        header.setTransTime(applySmsCodeRequest.getHeader().getTransTime());
        header.setTxnNum(channelCallCfgOpt.get().getCallChannelTxn());
        header.setBizType(AppParamConstant.DEFAULT_BIZ_TYPE);
        header.setInstId(applySmsCodeRequest.getHeader().getInstId());
        header.setSrcSysId(AppParamConstant.IGAS);
        header.setChanlId(ChannelEnum.BSPS.getChannelType());
        header.setTraceNo(GlobalEsbUtil.generateEsbSeqeuenceNumber(instId));
        GeneralSmsNoticeRequest generalSMSNoticeRequest = new GeneralSmsNoticeRequest();
        generalSMSNoticeRequest.setHeader(header);
        generalSMSNoticeRequest.setRealtimeFlag(AppParamConstant.YES);
        List<String> phoneNoList = new ArrayList<>();
        phoneNoList.add(mobileNo);
        generalSMSNoticeRequest.setPhoneList(phoneNoList);
        generalSMSNoticeRequest.setTemplateId(msgTemplateCfg.getTemplateCode());
        generalSMSNoticeRequest.setSmsContent(smsContent);
        Result<GeneralSmsNoticeResponse> result = (Result<GeneralSmsNoticeResponse>) dubboService.callDubboService(DubboMethodConstant.SMS_SEND_SERVICE, DubboMethodConstant.SMS_MSG_PUSH, generalSMSNoticeRequest);
        /* 重组响应结果 */
        BizResponse<ApplySmsCodeResponse> bizResponse = new BizResponse<>();
        if (null == result || null == result.getResult() || !BspsAppParamConstant.DUBBO_SUCCESS.equals(result.getResult().getRespCode())) {
            bizResponse.setRspSysId(AppParamConstant.SYS_ID);
            bizResponse.setRespCode(RespCodeEnum.SEND_SMS_CODE_ERROR.getRespCode());
            bizResponse.setRespDesc(RespCodeEnum.SEND_SMS_CODE_ERROR.getRespDesc());
            return bizResponse;
        }
        //短信验证码存入redis缓存
        userSessionInfo.setSmsVerifySeqNum(smsInfo.getVerifySeqNum());
        RedisUtil.onceSet(sessionId, JSONObject.toJSONString(userSessionInfo), BspsAppParamConstant.SESSION_EFFECTIVE_TIME);
        if (!StringUtil.isEmptyOrNull(mobileNo)) {
            applySmsCodeResponse.setPhoneNo(SensitiveDataUtil.desensitization("1", mobileNo).split("\\|")[0]);
        }
        bizResponse.setRspSysId(AppParamConstant.SYS_ID);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        bizResponse.setResult(applySmsCodeResponse);
        return bizResponse;
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        ApplySmsCodeResponse applySmsCodeResponse = (ApplySmsCodeResponse) bizResponse.getResult();
        ConvertUtil.convertInput(applySmsCodeResponse);
    }

    /**
     * 动态解析短信模板生成短信内容
     *
     * @param templateDesc 短信模板内容
     * @param smsCode      短信验证码
     * @return 短信内容
     * @throws Exception 异常
     */
    private String parseSmsTemplateInfo(String templateDesc, String smsCode) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        StringBuilder stringBuilder = new StringBuilder();
        while (!StringUtil.isEmptyOrNull(templateDesc) && templateDesc.contains("[")) {
            int startIndex = templateDesc.indexOf("[");
            stringBuilder.append(templateDesc, 0, startIndex);
            templateDesc = templateDesc.substring(startIndex + 1);
            int endIndex = templateDesc.indexOf("]");
            String key = templateDesc.substring(0, endIndex);
            if ("smsCode".equals(key.trim())) {
                stringBuilder.append(smsCode);
            } else if ("sysId".equals(key.trim())) {
                stringBuilder.append("商户服务平台");
            } else {
                String value = xmlTreeUtil.getXmlTreeStringValue(key.trim());
                if (null == value) {
                    rglog.error("根据动态模板获取字段值失败,key:<{}>", key);
                    throw new BizException(RespCodeEnum.SEND_SMS_CODE_ERROR.getRespCode(), RespCodeEnum.SEND_SMS_CODE_ERROR.getRespDesc());
                } else {
                    stringBuilder.append(value);
                }
            }
            templateDesc = templateDesc.substring(endIndex + 1);
        }
        stringBuilder.append(templateDesc);
        return stringBuilder.toString();
    }
}
